﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Windows.Forms;
using System.Reflection;

namespace Fonlow.BetterRobocopyGui
{
    /// <summary>
    /// Build Robocopy parameters in a line.
    /// </summary>
    public class ParametersBuilder
    {
        public ParametersBuilder(Options options)
        {
            this.options = options;
            propertiesArray = options.GetType().GetProperties();
        }

        Options options;

        /// <summary>
        /// All properties of options.
        /// </summary>
        PropertyInfo[] propertiesArray;

        /// <summary>
        /// Get default value of a property.
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns>Null if the default value is not defined. Empty string if the type is string. 0 if the type is int.</returns>
        static object GetDefaultValue(PropertyInfo propertyInfo)
        {
            object[] objects = propertyInfo.GetCustomAttributes(typeof(DefaultValueAttribute), false);
            if (objects.Length == 1)
            {
                return (objects[0] as DefaultValueAttribute).Value;
            }

            if (propertyInfo.PropertyType == typeof(string))
            {
                return String.Empty;
            }

            if (propertyInfo.PropertyType == typeof(int))
            {
                return 0;
            }

            return null;
        }

        /// <summary>
        /// Get display name of a property
        /// </summary>
        /// <param name="propertyInfo"></param>
        /// <returns>If DisplayNameAttribute does not exist, the property name will be used.</returns>
        static string GetDisplayName(PropertyInfo propertyInfo)
        {
            object[] objects = propertyInfo.GetCustomAttributes(typeof(DisplayNameAttribute), false);
            if (objects.Length == 1)
            {
                return (objects[0] as DisplayNameAttribute).DisplayName;
            }
            return propertyInfo.Name;
        }

        /// <summary>
        /// return a list of parameters from modified properties.
        /// </summary>
        /// <returns></returns>
        public List<string> GetDefinedParameters()
        {
            List<string> parameters = new List<string>();
            foreach (PropertyInfo p in propertiesArray)
            {
                object defaultValue = GetDefaultValue(p);
                object currentValue = p.GetValue(options, null);

                bool noDefaultValueSoOK = (defaultValue == null) && (currentValue != null);
                if (noDefaultValueSoOK)
                {
                    parameters.Add(GetDisplayName(p) + Convert.ToString(currentValue));
                }
                else
                {
                    bool propertyModified = (currentValue != null) && (defaultValue.ToString() != currentValue.ToString());
                    if (propertyModified)
                    {
                        if (p.PropertyType == typeof(bool))
                        {
                            parameters.Add(GetDisplayName(p));
                        }
                        else if (p.PropertyType == typeof(CopyFlags))
                        {
                            CopyFlagsConverter converter = new CopyFlagsConverter();
                            parameters.Add(GetDisplayName(p)+ converter.ConvertToString(currentValue));
                        }
                        else if (p.PropertyType == typeof(Rashcneto))
                        {
                            RashcnetoFlagsConverter converter = new RashcnetoFlagsConverter();
                            parameters.Add(GetDisplayName(p) + converter.ConvertToString(currentValue));
                        }
                        else
                        {
                            parameters.Add(GetDisplayName(p) +" "+ Convert.ToString(currentValue));
                        }
                    }
                }
            }
            return parameters;
        }

        public string GetParametersLine()
        {
            List<string> parameters = GetDefinedParameters();
            StringBuilder builder = new StringBuilder();
            foreach (string s in parameters)
            {
                builder.Append(s + " ");
            }
            return builder.ToString();
        }
    }
}
